package me.flyray.bsin.infrastructure.biz.paychannel.joinpay.util;

import cn.hutool.crypto.digest.DigestUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import me.flyray.bsin.infrastructure.biz.paychannel.joinpay.domain.request.BaseRequest;

import java.util.LinkedHashMap;
import java.util.stream.Collectors;

@Slf4j
public class SignatureUtil {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    private static final String SIGNATURE_FILED_KEY = "hmac";

    /**
     * 生成待签名字符串
     */
    public static <T extends BaseRequest> String buildSignatureString(T request) {
        try {
            // 1. 将对象转为 LinkedHashMap（保持字段顺序，自动忽略 null 值）
            LinkedHashMap<String, Object> fieldMap = objectMapper.convertValue(request, new TypeReference<>() {});

            // 2. 移除 hmac 字段
            fieldMap.remove(SIGNATURE_FILED_KEY);

            // 3. 按顺序拼接所有值
            String signatureString = fieldMap.values().stream()
                    .map(value -> {
                        if (value instanceof String) {
                            return (String) value;
                        } else {
                            try {
                                return objectMapper.writeValueAsString(value)
                                        .replaceAll("\"", "");
                            } catch (Exception e) {
                                return value.toString();
                            }
                        }
                    })
                    .collect(Collectors.joining(""));

            log.info("生成的待签名字符串: {}", signatureString);
            return signatureString;

        } catch (Exception e) {
            log.error("生成待签名字符串失败", e);
            throw new RuntimeException("生成待签名字符串失败", e);
        }
    }


    /**
     *
     * @param request
     * @param secretKey
     * @return
     * @param <T>
     */
    public static <T extends BaseRequest> String buildHmac(T request,String secretKey) {
        // 1. 生成待签名字符串
        String signatureString = buildSignatureString(request);
        return DigestUtil.md5Hex(signatureString + secretKey);

    }

}
